/*
 * =====================================================================================
 *
 *       Filename:  cl_socket_prototypes.hxx
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  05/28/2011 03:04:57 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Ken Chen (Ken), chen_kenz@emc.com
 *        Company:  EMC
 *
 * =====================================================================================
 */

#ifndef _CL_SOCKET_PROTOTYPES_HXX_
#define _CL_SOCKET_PROTOTYPES_HXX_

#include <unistd.h> 
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <cstring>
#include "cl_logger.hxx"

namespace neo
{
inline ssize_t clRead(int fildes, void *buf, size_t nbyte)   
{
  ssize_t siz = ::read(fildes, buf, nbyte);
  if(siz < 0)
  {
    char errmsg[512];
    int errcode = errno;
    CLLOG_E("NET", "clRead %d %s", 
        errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return siz;
}

inline ssize_t clReadv(int fildes, const struct iovec *iov, int iovcnt)
{
  return ::readv(fildes, iov, iovcnt);
}

inline ssize_t clWrite(int fildes, const void *buf, size_t nbyte)
{
  ssize_t siz = ::write(fildes, buf, nbyte);
  if(siz < 0)
  {
    char errmsg[512];
    int errcode = errno;
    CLLOG_E("NET", "clWrite %d %s", 
        errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return siz;
}

inline ssize_t clWritev(int fildes, const struct iovec *iov, int iovcnt)
{
  ssize_t siz = ::writev(fildes, iov, iovcnt);
  if(siz < 0)
  {
    char errmsg[512];
    int errcode = errno;
    CLLOG_E("NET", "clWritev %d %s", 
        errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return siz;
}

inline int clSocket(int domain, int type, int protocol)
{
  int socketfd = ::socket(domain, type, protocol);
  if(socketfd < 0)
  {
    char errmsg[512];
	  int errcode = errno;
    CLLOG_E("NET", "clSocket %d %s: ", 
				errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return socketfd;
}

inline int clBind(int sock, const struct sockaddr *address, socklen_t address_len)
{
  return ::bind(sock, address, address_len);
}

inline int clAccept(int sock, struct sockaddr *address, socklen_t* address_len)
{
  return ::accept(sock, address, address_len);
}

inline int clSetFdBlocking(int sockfd, bool isBlock)
{
  int flags = ::fcntl(sockfd, F_GETFL, 0);
  if(flags < 0)
  {
	  char errmsg[512];
	  int errcode = errno;
	  CLLOG_E("NET", "clSetFdBlocking: %d %s", 
				errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  	return flags;
  }

  int newflags;
  if(isBlock)
  {
  	newflags = flags & (~O_NONBLOCK);
  }
  else
  {
  	newflags = flags | O_NONBLOCK;
  }

  if((newflags != flags) && (flags = ::fcntl(sockfd, F_SETFL, newflags)) < 0)
  {
	  char errmsg[512];
	  int errcode = errno;
	  CLLOG_E("NET", "clSetFdBlocking %d %s", 
				errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return flags;
}

inline int clSetsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen)
{
  int res = ::setsockopt(sockfd, level, optname, optval, optlen);
  if(res < 0)
  {
	  char errmsg[512];
	  int errcode = errno;
	  CLLOG_E("NET", "clSetsocketopt %d %s", 
				errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }

  return res;
}

inline int clGetsockopt(int sockfd, int level, int optname, void* optval, socklen_t* optlen)
{
  return ::getsockopt(sockfd, level, optname, optval, optlen);
}

inline int clShutdown(int sock, int how)
{
  int res = ::shutdown(sock, how);
  if(res < 0)
  {
	  char errmsg[512];
	  int errcode = errno;
	  CLLOG_E("NET", "clShutdown %d %s", 
				errcode, strerror_r(errcode, errmsg, sizeof(errmsg)));
  }
  return res;
}

} // neo

#endif //_CL_SOCKET_PROTOTYPES_HXX_

